//@author A0081229H
package storage;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.TreeSet;

public class ClashingMaintenance {
	private Storage storage;
	private static ClashingMaintenance self = null;
	
	public ClashingMaintenance() throws NumberFormatException, Exception {
		storage = Storage.getInstance();
	}
	
	public static ClashingMaintenance getInstance() throws NumberFormatException, Exception {
		if (self == null) {
			self = new ClashingMaintenance();
			return self;
		} else {
			return self;
		}
	}
	
	public void maintainClashes() {
		if (storage.getSize() > 1) {
			LinkedList<Task> taskStack = new LinkedList<Task>();
			for (Iterator<Task> it = storage.iterator(); it.hasNext();) {
				Task cTask = it.next();
				cTask.setClashingStatus(false);
				taskStack.add(cTask);
			}
			TreeSet<Task> hypoTasks = new TreeSet<Task>();
			hypoTasks.add(taskStack.poll());
			while (!taskStack.isEmpty()) {
				Task cTask = taskStack.poll();
				maintainClashesAdd(cTask, hypoTasks);
				hypoTasks.add(cTask);
			}
		}
	}
	
	public void maintainClashesAdd(Task pTask, TreeSet<Task> pTasks) {
		assert (pTask == null || pTasks == null): Helper.ERROR_NULL;
		if (pTask.isTimed()) {
			ArrayList<Task> timedTasks = new ArrayList<Task>();
			for (Iterator<Task> it = pTasks.iterator(); it.hasNext();) {
				Task cTask = it.next();
				if (cTask.isTimed()) {
					timedTasks.add(cTask);
				}
			}
			if (timedTasks.size() > 0) {
				Task comparingTask = pTask;
				LinkedList<Task> clashingTasks = new LinkedList<Task>();
				DateRange dateRange = comparingTask.getDateRange();
				Date startDate = dateRange.getStartDate();
				Date endDate = dateRange.getEndDate();
				TimeRange timeRange = comparingTask.getTimeRange();
				Time startTime = timeRange.getStartTime();
				Time endTime = timeRange.getEndTime();
				for (Iterator<Task> it = timedTasks.iterator(); it.hasNext();) {
					Task comparedTask = it.next();
					DateRange cDateRange = comparedTask.getDateRange();
					Date cStartDate = cDateRange.getStartDate();
					Date cEndDate = cDateRange.getEndDate();
					TimeRange cTimeRange = comparedTask.getTimeRange();
					Time cStartTime = cTimeRange.getStartTime();
					Time cEndTime = cTimeRange.getEndTime();
					if (endDate.compareTo(cStartDate) == Helper.LESS ||
							startDate.compareTo(cEndDate) == Helper.MORE) {
						// no clash
					} else if ((endDate.compareTo(cStartDate) == Helper.SAME &&
							endTime.compareTo(cStartTime) != Helper.MORE) ||
							(startDate.compareTo(cEndDate) == Helper.SAME &&
							startTime.compareTo(cEndTime) != Helper.LESS)) {
						// no clash
					} else {
						// clash
						clashingTasks.add(comparedTask);
					}
				}
				if (!clashingTasks.isEmpty()) {
					clashingTasks.add(comparingTask);
					while (!clashingTasks.isEmpty()) {
						Task cTask = clashingTasks.poll();
						cTask.setClashingStatus(true);
					}
				}
			}
		}
	}
}
